package dyyx.util;

import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class JvmStatusUtil {
	
	private static final OperatingSystemMXBean op = ManagementFactory.getOperatingSystemMXBean(); 
    private static final ThreadMXBean tmb = ManagementFactory.getThreadMXBean(); 
    private static final 		ClassLoadingMXBean clmb = ManagementFactory.getClassLoadingMXBean();  
    private static final 		List<GarbageCollectorMXBean> gcmbs = ManagementFactory.getGarbageCollectorMXBeans();
    private static final 		List<MemoryPoolMXBean> mps = ManagementFactory.getMemoryPoolMXBeans();

    private static final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();

	public static Map<String,String> getStatus(){
		
		Map<String,String> map = new LinkedHashMap<String,String>();
		
		Runtime rt = Runtime.getRuntime();
		
		
		map.put("maxMemory", rt.maxMemory()+"");
		map.put("totalMemory", rt.totalMemory()+"");
		map.put("freeMemory", rt.freeMemory()+"");
		
		map.put("lastMinuteLoad", 	op.getSystemLoadAverage()+"");
	
		map.put("availableProcessors", rt.availableProcessors()+"");

		try {
			MemoryUsage mu = memoryBean.getHeapMemoryUsage();
			map.put("heapUsed", mu.getUsed() + "");
			mu = memoryBean.getNonHeapMemoryUsage();
			map.put("nonHeapUsed", mu.getUsed() + "");

		} catch (Throwable e) {

		}

		
		map.put("peakThreadCount", tmb.getPeakThreadCount()+"");
		map.put("threadCount", tmb.getThreadCount()+"");
		map.put("totalStartedThreadCount", tmb.getTotalStartedThreadCount()+"");
		map.put("daemonThreadCount", tmb.getDaemonThreadCount()+"");

	
		map.put("totalLoadedClassCount" ,clmb.getTotalLoadedClassCount()+"");  
		map.put("loadedClassCount",clmb.getLoadedClassCount()+"");  
		map.put("unloadedClassCount" , clmb.getUnloadedClassCount()+"");
		
		
		if (gcmbs != null) {
			int num = gcmbs.size();

			for (int i = 0; i < num; i++) {
				GarbageCollectorMXBean mb = gcmbs.get(i);
				String key = "gc" + i;
				StringBuilder sb = new StringBuilder();
				sb.append("name=" + mb.getName());
				sb.append(",count=" + mb.getCollectionCount());
				sb.append(",time=" + mb.getCollectionTime());
				map.put(key, sb.toString());
			}
		}
		

		if (mps != null) {
			int num = mps.size();

			for (int i = 0; i < num; i++) {
				MemoryPoolMXBean mb = mps.get(i);
				String key = "mempool" + i;
				StringBuilder sb = new StringBuilder();
				sb.append("name=" + mb.getName());
				sb.append(",type=" + mb.getType());
				sb.append(",usage=" + mb.getUsage());
				sb.append(",collectionUsage=" + mb.getCollectionUsage());


				map.put(key, sb.toString());
			}

		}
		
		
        
		return map;
	}
	
	
    public static ThreadInfo getThreadInfo(long id, int maxDepth){
    	return tmb.getThreadInfo(id, maxDepth);
    }
    
    public static ThreadInfo[] getThreadInfos(long[] ids, int maxDepth){
    	return tmb.getThreadInfo(ids, maxDepth);
    }
    
    public static ThreadInfo getThreadInfo(long id){
    	return tmb.getThreadInfo(id, 9);
    }
    
    public static ThreadInfo[] getThreadInfos(long[] ids){
    	return tmb.getThreadInfo(ids, 9);
    }
    
    
    public static MetricItems getMetrics(){
    	MetricItems metricItems = new MetricItems();
		Runtime rt = Runtime.getRuntime();

    	metricItems.add("maxMemory", rt.maxMemory());
    	
    	// metricItems.add("maxMemory", rt.maxMemory());
    	metricItems.add("totalMemory", rt.totalMemory());
    	metricItems.add("freeMemory", rt.freeMemory());
		
    	metricItems.add("lastMinuteLoad", 	op.getSystemLoadAverage());
	
    	metricItems.add("availableProcessors", rt.availableProcessors());

		try {
			MemoryUsage mu = memoryBean.getHeapMemoryUsage();
			metricItems.add("heapUsed", mu.getUsed());
			mu = memoryBean.getNonHeapMemoryUsage();
			metricItems.add("nonHeapUsed", mu.getUsed());

		} catch (Throwable e) {

		}

		
		metricItems.add("peakThreadCount", tmb.getPeakThreadCount());
		metricItems.add("threadCount", tmb.getThreadCount());
		metricItems.add("totalStartedThreadCount", tmb.getTotalStartedThreadCount());
		metricItems.add("daemonThreadCount", tmb.getDaemonThreadCount());

	
		metricItems.add("totalLoadedClassCount" ,clmb.getTotalLoadedClassCount());  
		metricItems.add("loadedClassCount",clmb.getLoadedClassCount());  
		metricItems.add("unloadedClassCount" , clmb.getUnloadedClassCount());
		
		
		if (gcmbs != null) {
			int num = gcmbs.size();

			for (int i = 0; i < num; i++) {
				GarbageCollectorMXBean mb = gcmbs.get(i);				
				metricItems.add("gcinfo_count", mb.getCollectionCount(),"name",mb.getName());
				metricItems.add("gcinfo_time", mb.getCollectionTime(),"name",mb.getName());

			}
		}
		

		if (mps != null) {
			int num = mps.size();

			for (int i = 0; i < num; i++) {
				MemoryPoolMXBean mb = mps.get(i);
				addMetricItem(mb,metricItems);
			}

		}
    	
    	return metricItems;
    }
    
    
    private static void addMetricItem(MemoryPoolMXBean mb,MetricItems metricItems){
    	TreeMap<String,String> labels = new TreeMap<String,String>();
    	labels.put("name", mb.getName());
    	labels.put("type", mb.getType().name());
    	labels.put("subtype", "used");
		metricItems.add("mempool", mb.getUsage().getUsed(),labels);
		
		labels = new TreeMap<String,String>(labels);
		labels.put("subtype", "init");
		metricItems.add("mempool", mb.getUsage().getInit(),labels);
		
		labels = new TreeMap<String,String>(labels);
		labels.put("subtype", "committed");
		metricItems.add("mempool", mb.getUsage().getCommitted(),labels);
		
		labels = new TreeMap<String,String>(labels);
		labels.put("subtype", "max");
		metricItems.add("mempool", mb.getUsage().getMax(),labels);
    }
    
   
	

}
